package com.ferry.protocol;

import com.ferry.common.util.SystemClock;
import com.ferry.protocol.payload.RequestPayload;
import com.ferry.protocol.payload.ResponsePayload;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ReplayingDecoder;

import java.util.List;

/**
 * Created by daiyong
 */
public class ProtocolDecoder extends ReplayingDecoder<ProtocolDecoder.State> {

	public ProtocolDecoder() {
		super(State.MAGIC);
	}

	private ProtocolHeader protocolHeader = new ProtocolHeader();

	@Override
	protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
		switch (state()) {
			case MAGIC:
				in.readShort(); //读取magic
				checkpoint(State.MESSAGE_TYPE);
			case MESSAGE_TYPE:
				protocolHeader.messageType(in.readByte());
				checkpoint(State.SERIALIZER_CODE);
			case SERIALIZER_CODE:
				protocolHeader.serializerType(in.readByte());
				checkpoint(State.STATUS);
			case STATUS:
				protocolHeader.statusCode(in.readByte());       // 状态位
				checkpoint(State.ID);
			case ID:
				protocolHeader.id(in.readLong());           // 消息id
				checkpoint(State.BODY_SIZE);
			case BODY_SIZE:
				protocolHeader.bodySize(in.readInt());      // 消息体长度
				checkpoint(State.BODY);
			case BODY:
				switch (protocolHeader.messageType()) {
					case (byte)0x03:
						System.out.println("heartbeat....");
						break;
					case (byte)0x01: {
						int length = protocolHeader.bodySize();
						byte[] bytes = new byte[length];
						in.readBytes(bytes);
						RequestPayload requestPayload = new RequestPayload(protocolHeader.id());
						requestPayload.timestamp(SystemClock.millisClock().time());
						requestPayload.bytes(protocolHeader.serializerType(), bytes);
						out.add(requestPayload);
						break;
					}
					case (byte)0x02: {
						int length = protocolHeader.bodySize();
						byte[] bytes = new byte[length];
						in.readBytes(bytes);
						ResponsePayload responsePayload = new ResponsePayload(protocolHeader.id());
						responsePayload.status(protocolHeader.statusCode());
						responsePayload.bytes(protocolHeader.serializerType(), bytes);
						out.add(responsePayload);
						break;
					}
					default:
						throw new IllegalArgumentException("序列化参数异常");
				}
				checkpoint(State.MAGIC);
		}
	}

	enum State {
		MAGIC,
		MESSAGE_TYPE,
		SERIALIZER_CODE,
		STATUS,
		ID,
		BODY_SIZE,
		BODY
	}
}
